#pragma once

#include "../umlmodel_global.h"

#include <memory>
#include <vector>

#include "CallConcurrencyKind.h"
#include "Feature.h"
#include "Namespace.h"

using std::make_shared;
using std::shared_ptr;
using std::vector;

namespace uml {
class Behavior;
class NamedElement;
class Namespace;
class Parameter;
class ParameterSet;
class Type;

/// <summary>
/// BehavioralFeature
/// A BehavioralFeature is a feature of a Classifier that specifies an aspect of the
/// behavior of its instances.  A BehavioralFeature is implemented (realized) by a
/// Behavior. A BehavioralFeature specifies that a Classifier will respond to a
/// designated request by invoking its implementing method.
/// </summary>
class UMLMODEL_EXPORT BehavioralFeature : public Feature, public Namespace {

public: // Constructors and destructors
    explicit BehavioralFeature(const QString& umlType="uml::BehavioralFeature");

public: // JsonSerializable override
    void fromJson(const QJsonObject& json, QStringList& errorList) override;
    void toJson(QJsonObject& json) override;

public: // Methods
    /// <summary>
    /// isDistinguishableFrom
    /// The query isDistinguishableFrom() determines whether two BehavioralFeatures may
    /// coexist in the same Namespace. It specifies that they must have different
    /// signatures.
    /// </summary>
    bool isDistinguishableFrom(shared_ptr<NamedElement> n, shared_ptr<Namespace> ns) const override;

    /// <summary>
    /// inputParameters
    /// The ownedParameters with direction in and inout.
    /// </summary>
    virtual shared_ptr<vector<Parameter>> inputParameters() const;

    /// <summary>
    /// outputParameters
    /// The ownedParameters with direction out, inout, or return.
    /// </summary>
    virtual shared_ptr<vector<Parameter>> outputParameters() const;

public: // Properties
    /// <summary>
    /// concurrency getter
    /// Specifies the semantics of concurrent calls to the same passive instance (i.e.,
    /// an instance originating from a Class with isActive being false). Active
    /// instances control access to their own BehavioralFeatures.
    /// </summary>
    CallConcurrencyKind concurrency() const;

    /// <summary>
    /// concurrency setter
    /// Specifies the semantics of concurrent calls to the same passive instance (i.e.,
    /// an instance originating from a Class with isActive being false). Active
    /// instances control access to their own BehavioralFeatures.
    /// </summary>
    void setConcurrency(CallConcurrencyKind value);

    /// <summary>
    /// isAbstract getter
    /// If true, then the BehavioralFeature does not have an implementation, and one
    /// must be supplied by a more specific Classifier. If false, the BehavioralFeature
    /// must have an implementation in the Classifier or one must be inherited.
    /// </summary>
    bool isAbstract() const;

    /// <summary>
    /// isAbstract setter
    /// If true, then the BehavioralFeature does not have an implementation, and one
    /// must be supplied by a more specific Classifier. If false, the BehavioralFeature
    /// must have an implementation in the Classifier or one must be inherited.
    /// </summary>
    void setIsAbstract(bool value);

    /// <summary>
    /// methods getter
    /// A Behavior that implements the BehavioralFeature. There may be at most one
    /// Behavior for a particular pairing of a Classifier (as owner of the Behavior) and
    /// a BehavioralFeature (as specification of the Behavior).
    /// </summary>
    vector<shared_ptr<Behavior>>& methods();

    /// <summary>
    /// ownedParameters getter
    /// The ordered set of formal Parameters of this BehavioralFeature.
    /// </summary>
    vector<shared_ptr<Parameter>>& ownedParameters();

    /// <summary>
    /// ownedParameterSets getter
    /// The ParameterSets owned by this BehavioralFeature.
    /// </summary>
    vector<shared_ptr<ParameterSet>>& ownedParameterSets();

    /// <summary>
    /// raisedExceptions getter
    /// The Types representing exceptions that may be raised during an invocation of
    /// this BehavioralFeature.
    /// </summary>
    vector<shared_ptr<Type>>& raisedExceptions();

private: // Fields
    /// <summary>
    /// concurrency
    /// Specifies the semantics of concurrent calls to the same passive instance (i.e.,
    /// an instance originating from a Class with isActive being false). Active
    /// instances control access to their own BehavioralFeatures.
    /// </summary>
    CallConcurrencyKind concurrency_ = CallConcurrencyKind::ksequential;

    /// <summary>
    /// isAbstract
    /// If true, then the BehavioralFeature does not have an implementation, and one
    /// must be supplied by a more specific Classifier. If false, the BehavioralFeature
    /// must have an implementation in the Classifier or one must be inherited.
    /// </summary>
    const static bool isAbstract_default_;
    bool isAbstract_= isAbstract_default_;

    /// <summary>
    /// methods
    /// A Behavior that implements the BehavioralFeature. There may be at most one
    /// Behavior for a particular pairing of a Classifier (as owner of the Behavior) and
    /// a BehavioralFeature (as specification of the Behavior).
    /// </summary>
    vector<shared_ptr<Behavior>> methods_;

    /// <summary>
    /// ownedParameters
    /// The ordered set of formal Parameters of this BehavioralFeature.
    /// </summary>
    vector<shared_ptr<Parameter>> ownedParameters_;

    /// <summary>
    /// ownedParameterSets
    /// The ParameterSets owned by this BehavioralFeature.
    /// </summary>
    vector<shared_ptr<ParameterSet>> ownedParameterSets_;

    /// <summary>
    /// raisedExceptions
    /// The Types representing exceptions that may be raised during an invocation of
    /// this BehavioralFeature.
    /// </summary>
    vector<shared_ptr<Type>> raisedExceptions_;

};

} // namespace uml
